package vue.panneau3;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.swing.JPanel;

import modele.Equation2D;
import vue.panneau3.panneau3Controleur.EtatPrecedantSuivantListener;
import vue.panneau3.panneau3Controleur.SelectionMatriceListener;
import vue.util.Point;

public class Representation2D extends JPanel implements MouseMotionListener,
		MouseListener, MouseWheelListener, KeyListener, EtatPrecedantSuivantListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private static String MODE_DEFAUT = "OBSERVATION";

	private static String MODE_DEPLACEMENT = "DEPLACEMENT";

	private static String MODE_ZOOM = "ZOOM";

	private String mode_actuel = MODE_DEFAUT;

	private Vector<Point> listePoints = new Vector<Point>();

	private Point pointCentre;

	private int zoom = 100;

	private float tailleCroix = 0.5f;

	private int vitesseZoom = 50; // en pourcent

	
	// viens de l ancienne methode pour gerer le
	// mousedragged
//	private int pourLeDeplacementX;
//
//	private int pourLeDeplacementY;

	private boolean afficherResultat = false;

	Image image;

	private Graphics2D g2D;

	private float fonctionAOptimiserX2;

	private float fonctionAOptimiserX1;

	private boolean afficherLaFonctionAOptimiser;

	private int positionPanneauXSouris;

	private int positionPanneauYSouris;

	private Vector<Equation2D> listeEquations = new Vector<Equation2D>();

	// le cadrillage
	private boolean afficherCadrillage = true;

	private float cadrillageFin = 1;

	private float cadrillageEpais = 5;

	private Color couleurCadrillageFin = new Color(0xDDDDDD);

	private Color couleurCadrillageEpais = new Color(0xCCCCCC);

	private boolean afficherPointRouge = true;

	private String libelleX1;

	private String libelleX2;

	private Vector<SelectionMatriceListener> listeDesEcouteurPourSelectionDeMatrice = new Vector<SelectionMatriceListener> () ;

	private Cursor curseurDefaut = new Cursor(Cursor.CROSSHAIR_CURSOR) ;
	private Cursor curseurPassageSurPoint = new Cursor(Cursor.HAND_CURSOR) ;

	private int pourLeDeplacementXCoordonnesSurPanneau;

	private int pourLeDeplacementYCoordonnesSurPanneau;

	private boolean montrerinformations = false ;

	private int zoneinfosSourisY = 40 ;

	private int zoneinfosSourisX = 100 ;

	private List<EtatPrecedantSuivantListener> listeDesEcouteurPourPassageEtatPrecedantSuivant = new ArrayList<EtatPrecedantSuivantListener> ();
	
//	private Random r = new Random(1) ;
	
	public float getCadrillageEpais() {
		return cadrillageEpais;
	}

	public void setCadrillageEpais(float cadrillageEpais) {
		this.cadrillageEpais = cadrillageEpais;
	}

	public float getCadrillageFin() {
		return cadrillageFin;
	}

	public void setCadrillageFin(float cadrillageFin) {
		this.cadrillageFin = cadrillageFin;
	}

	public Color getCouleurCadrillageEpais() {
		return couleurCadrillageEpais;
	}

	public void setCouleurCadrillageEpais(Color couleurCadrillageEpais) {
		this.couleurCadrillageEpais = couleurCadrillageEpais;
	}

	public Color getCouleurCadrillageFin() {
		return couleurCadrillageFin;
	}

	public void setCouleurCadrillageFin(Color couleurCadrillageFin) {
		this.couleurCadrillageFin = couleurCadrillageFin;
	}

	public Point getPointCentre() {
		return pointCentre;
	}

	public void setPointCentre(Point pointCentre) {
		this.pointCentre = pointCentre;
	}

	public float getTailleCroix() {
		return tailleCroix;
	}

	public void setTailleCroix(float tailleCroix) {
		this.tailleCroix = tailleCroix;
	}

	public int getZoom() {
		return zoom;
	}

	public void setZoom(int zoom) {
		if (zoom > 40) {
			this.zoom = zoom;
//			this.setTailleCroix(tailleCroix)
		}
	}

	/**
	 * ajouter un point qui apparaitra .
	 * 
	 * @param p
	 */
	public void ajouterPoint(Point p) {
		this.listePoints.add(p);
	}

	/**
	 * ajouter une equation2D qui apparaitra
	 * 
	 * @param p
	 */
	public void ajouterEquation2D(Equation2D e2D) {
		
		// si c est la premiere equation,
		// on adapte le zoom:
//		float zoomIdeal = 100 ;
		
		// on adapte a x1
		// on suppose que x2 = 0.
		if (e2D.getX1()!=0 && this.listeEquations.size()==0)
		{
//			float longueurAPartirDcGauche = e2D.getPartieDroite()/e2D.getX1() ;
			setZoom(3000) ;
		}
		
		this.listeEquations.add(e2D);
		repaint();
	}
	
	public void modifierEquation2D(Equation2D neweq,Equation2D equationCourante)
	{
		boolean trouve = false;
		int i = 0;
		while(i<listeEquations.size() && !trouve)
		{
			if(listeEquations.get(i) == equationCourante)
			{
				trouve = true;
			}
			else i++;
		}
		
		if(trouve)
		{
			Equation2D eq = listeEquations.get(i);
			eq.setX1(neweq.getX1());
			eq.setX2(neweq.getX2());
			eq.setPartieDroite(neweq.getPartieDroite());
			eq.setOperateur(neweq.getOperateur());
			eq.setCouleur(neweq.getCouleur());
		}
		repaint();
	}

	/**
	 * tout reinitialiser
	 * 
	 */
	public void reinitialiser() {
		this.listeEquations = new Vector<Equation2D>();
		this.listePoints = new Vector<Point>();
//		pointCentre = new Point(0, 0);
//		tailleCroix = 2;
//		zoom = 100;
//		vitesseZoom = 10;
		this.repaint();
	}

	/***************************************************************************
	 * construit le graphique 2D (panneau). la liste des points peut valoir
	 * null.
	 * 
	 * la liste des equations aussi peut etre nulle.
	 * 
	 * @param listePoints
	 * @param fonctionAOptimiserX1
	 * @param fonctionAOptimiserX2
	 */
	public Representation2D(Vector<Point> listePoints,
			float fonctionAOptimiserX1, float fonctionAOptimiserX2,
			Vector<Equation2D> listeEquations) {

		if (listePoints != null)
			this.listePoints = listePoints;

		if (listeEquations != null)
			this.listeEquations = listeEquations;

		pointCentre = new Point(0, 0);

		this.setfonctionAOptimiserX1(fonctionAOptimiserX1);
		this.setfonctionAOptimiserX2(fonctionAOptimiserX2);

		this.addMouseMotionListener(this);
		this.addMouseListener(this);
		this.addMouseWheelListener(this);
		this.addKeyListener(this);
	
		
		this.addEtatPrecedantSuivantListener(this) ;
		
//		
//		new Thread() {
//			public void run() {
//				
//				while (true) {
//					try {
//						Thread.sleep(100) ;
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					}
//					int res = r.nextInt()%4 ;
//					System.out.println("resultat = "+res);
//					if (res==0)
//						deplaceADroite() ;
//					if (res==1)
//						deplaceAGauche() ;
//					if (res==2)
//						deplaceEnBas() ;
//					if (res==3)
//						deplaceEnHaut() ;
//					repaint() ;
//				}
//			}
//		}.start() ;
	}

	public void setfonctionAOptimiserX2(float fonctionAOptimiserX2) {
		this.fonctionAOptimiserX2 = fonctionAOptimiserX2;
		repaint();
	}

	public void setfonctionAOptimiserX1(float fonctionAOptimiserX1) {
		this.fonctionAOptimiserX1 = fonctionAOptimiserX1;
		repaint();
	}

	@Override
	protected synchronized void paintComponent(Graphics arg0) {
		super.paintComponent(arg0);

		// /////////
		// rafraichir couleur
		// on ne veut pas
		// avoir tout les
		// points de la meme
		// couleur.

		// on a une liste de couleur,
		// on fait une division
		// et on recupere a chaque
		// etape la couleur qui va bien.
		// if (rafraichirCouleur) {
		// for (Point point : listePoints) {
		// point.setCouleur( Point.LISTE_COULEUR[
		// point.getnumero()%
		// Point.LISTE_COULEUR.length
		// ]) ;
		// }
		// rafraichirCouleur = false ;
		// }
		// /////////

		// on fait un rendu dans un buffer.
		// on affichera le buffer a la fin.
		// si on est pas au premier appel
		if (image != null) {
			// si la taille a change:
			if (image.getHeight(this) != this.getHeight()
					|| image.getWidth(this) != this.getWidth()) {
				image = createImage(this.getWidth(), this.getHeight());
				this.g2D = (Graphics2D) image.getGraphics();
			}
			// si on est au premier appel
		} else {
			image = createImage(this.getWidth(), this.getHeight());
			this.g2D = (Graphics2D) image.getGraphics();
		}

		/******************************
		 * ////////////////////////////
		 *  //// LES OPTIMISATIONS ////
		 * ////////////////////////////
		 *****************************/

		// optimisations diverses
		// je n ai pas vraiment remarque de differences ...
		// : sur le graphics.
		/** D�sactivation de l'anti-aliasing */
		g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_OFF);
		// g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
		// RenderingHints.VALUE_ANTIALIAS_ON);
		g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
		/** Demande de rendu rapide */
		g2D.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_SPEED);
		g2D.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
				RenderingHints.VALUE_COLOR_RENDER_SPEED);
		g2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
				RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
		g2D.setRenderingHint(RenderingHints.KEY_DITHERING,
				RenderingHints.VALUE_DITHER_DISABLE);

		// on colorie tout en gris clair.
		g2D.setColor(new Color(0xEEEEEE));
		g2D.fillRect(0, 0, this.getWidth(), this.getHeight());
		g2D.setColor(Color.BLACK);

		// taille du texte a 20 !
		g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
				20));

		// on affice les reperes :
		Point point00 = retrouveCoordonneesAPartirDuVraiPoint(new Point(0, 0));


		/***************************
		 * ///////////////////////// 
		 * //// LES QUADRILLAGE ////
		 * /////////////////////////
		 **************************/

		g2D.setClip((int)point00.getX()-15,
				30,
				this.getWidth() - (int)point00.getX()-15 ,
				(int)point00.getY() + 15);
		if (this.isAfficherCadrillage()) {

			// on essaye de faire des cadrillage :

			float cadrillageF = 0.1f;
			while (cadrillageF * this.getZoom() / 100 < this.getHeight() / 10) {
				cadrillageF = cadrillageF * 10;
			}
			this.setCadrillageFin(cadrillageF / 10);
			this.setCadrillageEpais(cadrillageF / 2);

			// System.out.println("cadrillage f="+this.getCadrillageFin()+"
			// e="+this.getCadrillageEpais());

			// le cadrillage epais
			g2D.setColor(this.getCouleurCadrillageEpais());
			g2D.setStroke(new BasicStroke(2.0f));

			if (this.getCadrillageEpais() * this.getZoom() / 100 != 0) {
				// en X1
				// de 0 a droite
				for (int i = 0; i < 50; i++) {
					g2D.drawLine(
							(int) (point00.getX() + i * this.getCadrillageEpais() * this.getZoom() / 100),
							 15,
							(int) (point00.getX() + i * this.getCadrillageEpais() * this.getZoom() / 100),
							(int) (point00.getY()+15));
				}
				// de 0 a gauche
//				for (int i = 0; i < 50; i++) {
//					g2D.drawLine(
//							(int) (point00.getX() - i * this.getCadrillageEpais() * this.getZoom() / 100),
//							15,
//							(int) (point00.getX() - i * this.getCadrillageEpais() * this.getZoom() / 100),
//							this.getHeight() - 15);
//				}
				// en X2
				// de 0 en bas
//				for (int i = 0; i < 50; i++) {
//					g2D.drawLine(
//							15,
//							(int) (point00.getY() + i * this.getCadrillageEpais() * this.getZoom() / 100),
//							this.getWidth() - 15, 
//							(int) (point00.getY() + i * this.getCadrillageEpais() * this.getZoom() / 100)
//							);
//				}
				// de 0 en haut
				for (int i = 0; i < 50; i++) {
					g2D.drawLine(
							(int) (point00.getX()-15),
							(int) (point00.getY() - i * this.getCadrillageEpais() * this.getZoom() / 100),
							this.getWidth() - 15, 
							(int) (point00.getY() - i * this.getCadrillageEpais() * this.getZoom() / 100));
				}

			}

			// le cadrillage fin
			g2D.setColor(this.getCouleurCadrillageFin());
			g2D.setStroke(new BasicStroke(1.0f));

			if (this.getCadrillageFin() * this.getZoom() / 100 != 0) {
				// en X1
				// de 0 a droite
				for (int i = 0; i < 200; i++) {
					g2D.drawLine(
							(int) (point00.getX() + i * this.getCadrillageFin() * this.getZoom() / 100),
							15,
							(int) (point00.getX() + i * this.getCadrillageFin() * this.getZoom() / 100),
							(int) (point00.getY()+15));
				}
				// de 0 a gauche
//				for (int i = 0; i < 200; i++) {
//					g2D.drawLine(
//							(int) (point00.getX() - i * this.getCadrillageFin() * this.getZoom() / 100),
//							15,
//							(int) (point00.getX() - i * this.getCadrillageFin() * this.getZoom() / 100),
//							this.getHeight() - 15);
//				}
				// en X2
				// de 0 en bas
//				for (int i = 0; i < 200; i++) {
//					g2D.drawLine(
//							15,
//							(int) (point00.getY() + i * this.getCadrillageFin() * this.getZoom() / 100),
//							this.getWidth() - 15,
//							(int) (point00.getY() + i * this.getCadrillageFin() * this.getZoom() / 100));
//				}
				// de 0 en haut
				for (int i = 0; i < 200; i++) {
					g2D.drawLine(
							(int) (point00.getX()-15),
							(int) (point00.getY() - i * this.getCadrillageFin() * this.getZoom() / 100),
							this.getWidth() - 15,
							(int) (point00.getY() - i * this.getCadrillageFin() * this.getZoom() / 100));
				}
			}
			

				// un petit texte pour indiquer le 1x
			// sur x1:
			
			g2D.setColor(Color.DARK_GRAY);

			// le dessous du texte:
			String texte = ""+this.getCadrillageEpais() ;
			g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
					15));
			FontMetrics fontMetrics = g2D.getFontMetrics();
			int longueur = fontMetrics.stringWidth(texte);
			int hauteur = fontMetrics.getHeight();
			g2D.drawString(texte,
					(int) (point00.getX() + this.getCadrillageEpais() * this.getZoom() / 100) - longueur/2,
					(int)point00.getY()+20) ;
			g2D.setColor(this.getCouleurCadrillageEpais());

			
			
			// sur x2 avec le grand repere :
			
			// sur x2: *1
			
			g2D.setColor(Color.DARK_GRAY);
			g2D.setClip(0,
					0,
					this.getWidth(),this.getHeight());
			g2D.drawString(texte,
					(int) point00.getX() - longueur - 5,
					(int) (point00.getY() - this.getCadrillageEpais() * this.getZoom() / 100) + hauteur/4) ;
			g2D.setColor(this.getCouleurCadrillageEpais());			
			
			// sur x2: *5
			
			texte = ""+(this.getCadrillageEpais()*5) ;
			g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
					15));
			fontMetrics = g2D.getFontMetrics();
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.setColor(Color.DARK_GRAY);
			g2D.setClip(0,
					0,
					this.getWidth(),this.getHeight());
			g2D.drawString(texte,
					(int) point00.getX() - longueur - 5,
					(int) (point00.getY() - 5*this.getCadrillageEpais() * this.getZoom() / 100) + hauteur/4) ;
			g2D.setColor(this.getCouleurCadrillageEpais());			
			
			
			
			// sur x2:
			
			g2D.setColor(Color.DARK_GRAY);
			g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
					12));
			fontMetrics = g2D.getFontMetrics();
			texte = ""+this.getCadrillageFin() ;
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.drawString(texte,
					(int) point00.getX() - longueur - 5,
					(int) (point00.getY() - this.getCadrillageFin() * this.getZoom() / 100) + hauteur/2) ;
			g2D.setColor(this.getCouleurCadrillageEpais());

		}
		
		
		// le cadre autour du mot informations
		if (!this.montrerinformations)
		{
			// si on ne montre pas les infos:
			g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
					20));			g2D.setClip(0, 0, this.getWidth(), this.getHeight());
			g2D.setColor(Color.LIGHT_GRAY);
			zoneinfosSourisX = g2D.getFontMetrics().stringWidth("informations") + 30;
			g2D.drawRect(15,
					15,
					zoneinfosSourisX-15,
					zoneinfosSourisY-15) ;
			g2D.drawString("informations", 20, zoneinfosSourisY-5) ;
		}

		
		

		/***********************
		 * /////////////////////
		 * //// LES REPERES ////
		 * /////////////////////
		 **********************/

		g2D.setClip(0, 0, this.getWidth(), this.getHeight());
		g2D.setStroke(new BasicStroke(2.0f));
		g2D.setColor(Color.BLACK);
		// taille du texte a 20 !
		g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
				20));
		// le repere Y
		// la fleche
		g2D.drawLine((int)point00.getX() - 5, 15, (int)point00.getX(), 5);
		g2D.drawLine((int)point00.getX() + 5, 15, (int)point00.getX(), 5);
		// la ligne
		// on peut couper la ligne si elle passe sur le texte
		// et qu on affiche les infos
		
		
		if (point00.getX()<=180 && this.montrerinformations)
		{
			// on trace deux lignes ,
			// une en haut,
			// et une en bas du texte
			g2D.drawLine((int)point00.getX(), 5, (int)point00.getX(), 60);
			g2D.drawLine((int)point00.getX(), 240, (int)point00.getX(), this.getHeight() - 5);
		} else {
		g2D.drawLine((int)point00.getX(), 5, (int)point00.getX(), this.getHeight() - 5);
		}
		// // un texte
		// g2D.drawString("x2", point00.getX()+10, 30) ;

		// le repere X
		// la fleche
		g2D.drawLine(this.getWidth() - 15, (int)point00.getY() - 5,
		this.getWidth() - 5, (int)point00.getY());
		g2D.drawLine(this.getWidth() - 15, (int)point00.getY() + 5,
				this.getWidth() - 5, (int)point00.getY());
//		g2D.drawLine(this.getWidth() - 15, (int)point00.getY() - 5,
//				this.getWidth() - 5, (int)point00.getY());
		// la ligne
		// si on passe sur le texte,
		// il est de bon ton de commencer la ligne apres le texte
		if (point00.getY()<240 && this.montrerinformations) {
			g2D.drawLine(210, (int)point00.getY(), this.getWidth() - 5, (int)point00.getY());
		} else {
			g2D.drawLine(15, (int)point00.getY(), this.getWidth() - 5, (int)point00.getY());
		}
		// // un texte
		// g2D.drawString("x1", this.getWidth()-35,point00.getY()+25) ;

		g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
				20));

		/*************************
		 * ///////////////////////
		 * //// LES EQUATIONS ////
		 * ///////////////////////
		 *************************/

//		g2D.setClip(190, 20, this.getWidth() - 205,
//		this.getHeight() - 45);

//		g2D.setClip((int)point00.getX()-15,
//				20,
//				this.getWidth() - 205,
//				(int)point00.getY()+15);

		g2D.setClip((int)point00.getX()-5,
				20,
				100000,
				(int)point00.getY()+5-20 );

		
		
		
		
		for (Equation2D eq : this.listeEquations) {

				// il y a deux possibilites,
				// aX1 + bX2 = c avec a=0 ;
				// la il faut ruser
				// le reste
				// la tout se passe bien.

				
				// difficulte
				if (eq.getX1() == 0) {
	
					Point pointDePassageDeEq = new Point(0, (eq.getPartieDroite() / eq.getX2()));
					Point pointSurLePanneau = this.retrouveCoordonneesAPartirDuVraiPoint(pointDePassageDeEq);
	
					g2D.setColor(eq.getCouleur());
					g2D.setStroke(new BasicStroke(2.0f));
					g2D.drawLine(200, (int)pointSurLePanneau.getY(),
							this.getWidth() - 20, (int)pointSurLePanneau.getY());
	
					// un petit pointille pour dire si <= ou >=
					float epaisseur = 2.0f;
					/** taille de la ligne */
					float[] style = { 10, 5 };
					/** les pointill�s seront 2 fois plus long que les blancs */
					g2D.setStroke(new BasicStroke(epaisseur, BasicStroke.CAP_BUTT,
							BasicStroke.JOIN_MITER, 10.0f, style, 0));
					if (eq.getOperateur().equals("<=")) {
						g2D.drawLine(205, (int)pointSurLePanneau.getY() + 3, this
								.getWidth() - 25, (int)pointSurLePanneau.getY() + 3);
					} else {
						g2D.drawLine(205, (int)pointSurLePanneau.getY() - 3, this
								.getWidth() - 25, (int)pointSurLePanneau.getY() - 3);
					}
					g2D.setStroke(new BasicStroke(1.0f));
	
					// tout va bien
				} else {
	
					// encore une petite difficultee
					if (eq.getX2() == 0) {
						
						// on a une ligne verticale,
						// c est donc facile .
						float coord_x = (this.retrouveCoordonneesAPartirDuVraiPoint(
								new Point(eq.getPartieDroite()/eq.getX1(),0))).getX() ;
						
						g2D.setColor(eq.getCouleur());
						g2D.setStroke(new BasicStroke(2.5f));						
						g2D.drawLine((int)(coord_x), 20, (int)(coord_x), this.getHeight());
						
						int decalageSurX = 0 ;
						
						if (eq.getOperateur().equals("<=")) {
							decalageSurX -= 3;
						} else {
							decalageSurX += 3;
						}
						float epaisseur = 2.0f;
						/** taille de la ligne */
						float[] style = { 10, 5 };
						/** les pointill�s seront 2 fois plus long que les blancs */
						g2D.setStroke(new BasicStroke(epaisseur, BasicStroke.CAP_BUTT,
								BasicStroke.JOIN_MITER, 10.0f, style, 0));
						g2D.drawLine((int)(coord_x) + decalageSurX, 20, (int)(coord_x) + decalageSurX, this.getHeight());
						
						
						
						
						
					}else {
					
					
						float p1x = 0;
						float p1y = 0;
		
						// on a une equation aX1 + bX2 = c
						// on dira que X1 = 0
						// on a X2 = c/b
		
						float p2x = ((this.getHeight() * eq.getX2()) / eq.getX1());
						float p2y = this.getHeight();
		
						Point pointDePassageDeEq = new Point(0, (eq.getPartieDroite() / eq.getX2()));
						Point pointSurLePanneau = this
								.retrouveCoordonneesAPartirDuVraiPoint(pointDePassageDeEq);
						float decalageSurX = pointSurLePanneau.getX()
								-  ((pointSurLePanneau.getY() * eq.getX2()) / eq.getX1());
		
						g2D.setColor(eq.getCouleur());
						g2D.setStroke(new BasicStroke(2.5f));
						g2D.drawLine((int)(p1x + decalageSurX), (int)p1y, (int) (p2x + decalageSurX), (int)p2y);
		
						// un petit pointille pour sire si <= ou >=
						int decalageSurY = 0 ;
						if (eq.getOperateur().equals("<=")) {
							decalageSurX -= 2;
							decalageSurY -= 2;
						} else {
							decalageSurX += 2;
							decalageSurY += 2;
						}
						float epaisseur = 2.0f;
						/** taille de la ligne */
						float[] style = { 10, 5 };
						/** les pointill�s seront 2 fois plus long que les blancs */
						g2D.setStroke(new BasicStroke(epaisseur, BasicStroke.CAP_BUTT,
								BasicStroke.JOIN_MITER, 10.0f, style, 0));
						g2D.drawLine((int) (p1x + decalageSurX), (int) p1y-decalageSurY, (int) (p2x + decalageSurX), (int)p2y-decalageSurY);
					
					}
					
					g2D.setStroke(new BasicStroke(1.0f));
	
				}
		}

		// le point rouge:
		g2D.setClip((int)point00.getX() - 10, (int)point00.getY() - 10, 20, 20);

		if (this.isAfficherPointRouge()) {
			g2D.setColor(Color.RED);
			g2D.fillOval((int)point00.getX() - 4, (int)point00.getY() - 4, 8, 8);
		}

		/********************************
		 * //////////////////////////////
		 * //// FONCTION A OPTIMISER ////
		 * //////////////////////////////
		 *******************************/

		g2D.setClip(180, 20, this.getWidth() - 200, this.getHeight() - 45);
		if (this.afficherLaFonctionAOptimiser) {

			int p1x = 0;
			int p1y = 0;

			int p2x = (int) ((this.getHeight() * this.fonctionAOptimiserX2) / this.fonctionAOptimiserX1);
			int p2y = this.getHeight();

			int decalageSurX = this.positionPanneauXSouris
					- (int) ((this.positionPanneauYSouris * this.fonctionAOptimiserX2) / this.fonctionAOptimiserX1);

			g2D.setColor(Color.RED);
			g2D.setStroke(new BasicStroke(3.0f));
			g2D.drawLine(p1x + decalageSurX, p1y, p2x + decalageSurX, p2y);
			g2D.setStroke(new BasicStroke(1.0f));

		}

		// on construit avec des coordonnees relative au panneau
		// on prend un vecteur de tout les points a afficher.
		// alors on retrouve les coordonnees sur le jpanel.
		//
		// contourPanneau contient les points avec les coordonnees
		// relatives au jpanel !
		// ce qui facilite l affichage .
		Vector<Point> listePointsPanneau = new Vector<Point>();
		for (Point point : listePoints) {
			Point p = retrouveCoordonneesAPartirDuVraiPoint(point);
			p.setCouleur(point.getCouleur());
			p.setAfficheNumero(point.isAfficheNumero());
			p.settext(point.toString());
			listePointsPanneau.add(p);
		}
		
		
		
		
		
		
		
		/************************
		 * //////////////////////
		 * //// INFORMATIONS ////
		 * //////////////////////
		 ***********************/

		
		if (this.montrerinformations)
		{
			
			
			g2D.setClip(0, 0, this.getWidth(), this.getHeight());
	
			// g2D.setColor(new Color(0xDDDDDD)) ;
			// g2D.fillRect(4,4, 150, 100) ;
			// le niveau de zoom.
			// g2D.setFont(new
			// Font(g2D.getFont().getName(),g2D.getFont().getStyle(),15)) ;
			g2D.setFont(new Font(g2D.getFont().getName(), Font.BOLD, 15));
	
			// zoom
			// le dessous du texte:
			String texte = "Niveau de zoom : " + (float) this.getZoom() / 100 ;
			FontMetrics fontMetrics = g2D.getFontMetrics();
			int longueur = fontMetrics.stringWidth(texte);
			int hauteur = fontMetrics.getHeight();
			g2D.setColor(new Color(0xEEEEEE));
			g2D.fillRect(10, 80-hauteur, longueur, hauteur) ;
			g2D.setColor(Color.BLACK);
			g2D.drawString(texte,
					10,
					80);
	
			// le quadrillage
			// le dessous du texte:
			texte = "Quadrillage : [ " + this.getCadrillageEpais() + " , "
			+ this.getCadrillageFin()+" ]" ;
			fontMetrics = g2D.getFontMetrics();
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.setColor(new Color(0xEEEEEE));
			g2D.fillRect(10, 100-hauteur, longueur, hauteur) ;
			g2D.setColor(Color.BLACK);
				g2D.drawString(texte, 10, 100);
	
				
				
			// la fonction a optimiser
			// if (this.afficherLaFonctionAOptimiser) {
			// g2D.setColor(Color.RED) ;
				// le dessous du texte:
				texte = "Optimiser : " + this.fonctionAOptimiserX1 + " X1 + "
				+ this.fonctionAOptimiserX2 + " X2" ;
				fontMetrics = g2D.getFontMetrics();
				longueur = fontMetrics.stringWidth(texte);
				hauteur = fontMetrics.getHeight();
				g2D.setColor(new Color(0xEEEEEE));
				g2D.fillRect(10, 120-hauteur, longueur, hauteur) ;
				g2D.setColor(Color.BLACK);
			g2D.drawString(texte, 10, 120);
			// }
	
			
			
			// le point rouge
			if (this.isAfficherPointRouge()) {
				// le dessous du texte:
				texte = "Point rouge : oui" ;
				fontMetrics = g2D.getFontMetrics();
				longueur = fontMetrics.stringWidth(texte);
				hauteur = fontMetrics.getHeight();
				g2D.setColor(new Color(0xEEEEEE));
				g2D.fillRect(10, 140-hauteur, longueur, hauteur) ;
				g2D.setColor(Color.BLACK);
				g2D.drawString("Point rouge : oui",
						10,
						140);
			} else {
				// le dessous du texte:
				texte = "Point rouge : non" ;
				fontMetrics = g2D.getFontMetrics();
				longueur = fontMetrics.stringWidth(texte);
				hauteur = fontMetrics.getHeight();
				g2D.setColor(new Color(0xEEEEEE));
				g2D.fillRect(10, 140-hauteur, longueur, hauteur) ;
				g2D.setColor(Color.BLACK);
				g2D.drawString("Point rouge : non", 
						10, 
						140);
			}
	
			// la vitesse de zoom
			// le dessous du texte:
			texte = "Vitesse de Zoom : " + this.getVitesseZoom() ;
			fontMetrics = g2D.getFontMetrics();
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.setColor(new Color(0xEEEEEE));
			g2D.fillRect(10, 170-hauteur, longueur, hauteur) ;
			g2D.setColor(Color.BLACK);
			g2D.drawString(texte, 
					10, 
					170);
	
			// le mode actuel
			// le dessous du texte:
			texte = "Mode : " + this.mode_actuel ;
			fontMetrics = g2D.getFontMetrics();
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.setColor(new Color(0xEEEEEE));
			g2D.fillRect(10, 190-hauteur, longueur, hauteur) ;
			g2D.setColor(Color.BLACK);
			g2D.drawString("Mode : " + this.mode_actuel,
					10,
					190);
	
			// la taille des croix
			texte = "Taille des croix : " + this.tailleCroix+" unites" ;
			fontMetrics = g2D.getFontMetrics();
			longueur = fontMetrics.stringWidth(texte);
			hauteur = fontMetrics.getHeight();
			g2D.setColor(new Color(0xEEEEEE));
			g2D.fillRect(10, 210-hauteur, longueur, hauteur) ;
			g2D.setColor(Color.BLACK);
			g2D.drawString(texte,
					10, 
					210);
	
		}// fin if montrer informations
		
		
		
		
		
		/************************
		 * //////////////////////
		 * ////  X1 et X2    ////
		 * //////////////////////
		 ***********************/
		
		g2D.setClip(0, 0, this.getWidth(), this.getHeight());
		g2D.setFont(new Font(g2D.getFont().getName(), Font.PLAIN,
				20));
		
		
		
		g2D.setColor(Color.DARK_GRAY);
		g2D.setStroke(new BasicStroke(2.0f));

		// un texte
		if (libelleX2==null)
			libelleX2 = "" ;
		g2D.drawString("x2 :", point00.getX() + 10, 30);
		FontMetrics fontMetrics = g2D.getFontMetrics();
		int hauteur = fontMetrics.getHeight();
		g2D.drawString(this.libelleX2, point00.getX() + 13, 34 + hauteur);

		// un texte
		if (libelleX1==null)
			libelleX1 = "" ;
		g2D.drawString("x1 : ", this.getWidth() - 35, point00.getY() + 25);
		// connaitre la taille du texte en pixels
		int longueur = fontMetrics.stringWidth(this.libelleX1) + 18;
		hauteur = fontMetrics.getHeight();
		g2D.drawString(this.libelleX1, this.getWidth() - longueur, point00.getY() + 25 + hauteur);
		

		// le texte "0,0"
		// en taille 10 !
		g2D.setFont(new Font(g2D.getFont().getName(), g2D.getFont().getStyle(),
				10));
		g2D.drawString("(0,0)", point00.getX() - 30, point00.getY() + 15);

		
		
		
		
		
		
		
		

		/**********************
		 * ////////////////////
		 * //// LES POINTS ////
		 * ////////////////////
		 *********************/

		g2D.setClip(0, 0, this.getWidth(), this.getHeight());
		g2D.setFont(new Font(g2D.getFont().getName(), Font.PLAIN,
				20));
		for (Point p : listePointsPanneau) {

			// on trace la croix
			g2D.setColor(p.getCouleur());
			g2D.setStroke(new BasicStroke(3.0f));
			g2D.drawLine((int)p.getX() - (int) (this.tailleCroix * this.getZoom() / 100),
					(int)p.getY(),
					(int)p.getX() + (int) (this.tailleCroix * this.getZoom() / 100),
					(int)p.getY());
			g2D.drawLine((int)p.getX(), 
					(int)p.getY() - (int) (this.tailleCroix * this.getZoom() / 100),
					(int)p.getX(), (int)p.getY() + (int) (this.tailleCroix* this.getZoom() / 100));
			g2D.setStroke(new BasicStroke(1.0f));

		}

		int[] xpoint = new int[listePoints.size()];
		int[] ypoint = new int[listePoints.size()];

		// les textes sur les points .
		int i = -1;
		boolean afficheAuMoinsUneInfoPoint = false ;
		for (Point p : listePointsPanneau) {
			i++;
			xpoint[i] = (int)p.getX();
			ypoint[i] = (int)p.getY();

			if (p.isAfficheNumero()) {

				
				afficheAuMoinsUneInfoPoint = true;
				// on met un curseur mieu:
				setCursor(this.getCurseurPassageSurPoint());
				
				/** 80 % de transparence */
				g2D.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, 0.9f));

				g2D.setColor(new Color(40, 40, 50));

				// connaitre la taille du texte en pixels
				fontMetrics = g2D.getFontMetrics();
				longueur = fontMetrics.stringWidth(p.toString()) + 10;
				hauteur = fontMetrics.getHeight();

				g2D.setStroke(new BasicStroke(2.0f));
				g2D.fillRect((int)p.getX() - longueur / 2, (int)p.getY() - hauteur - 10,
						longueur, hauteur + 5);
				g2D.setColor(p.getCouleur());
				g2D.drawRect((int)p.getX() - longueur / 2, (int)p.getY() - hauteur - 10,
						longueur, hauteur + 5);

				g2D.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, 1.0f));
				g2D.setStroke(new BasicStroke(1.0f));

				g2D.setColor(Color.WHITE);
				g2D.drawString(p.toString(), p.getX() - longueur / 2 + 6, p
						.getY() - 11);
				g2D.setColor(p.getCouleur());
				g2D.drawString(p.toString(), p.getX() - longueur / 2 + 6, p
						.getY() - 12);

			}
		}
		if (!afficheAuMoinsUneInfoPoint) {
			setCursor(this.getCurseurDefaut());
		}


		
		
		
		
		/************************
		 * //////////////////////
		 * ////    DESIGN    ////
		 * //////////////////////
		 ***********************/

		g2D.setComposite(AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 0.3f));
		
		g2D.setColor(Color.DARK_GRAY);
		g2D.setStroke(new BasicStroke(1.0f));

		g2D.drawLine(this.getWidth()/30, 4, 29*this.getWidth()/30 , 4) ;
		
		g2D.setStroke(new BasicStroke(2.0f));
		g2D.drawLine(this.getWidth()/30-3, 7, 29*this.getWidth()/30+3 , 7) ;
		
		g2D.setColor(Color.BLACK);
		g2D.drawLine(this.getWidth()/30-6, 10,  29*this.getWidth()/30+6 , 10) ;
		
		g2D.setComposite(AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 1.0f));
		
		
		
		
		
		
		// on met le buffer sur le panneau.
		arg0.drawImage(image, 0, 0, this);

	}

	// ici on fait le decalage.
	public void mouseDragged(MouseEvent arg0) {

		
		// soit on fait un dragged,
		//  soit un moved
		// donc dans les deux cas,
		// si on veut avoir la fonction a optimiser
		// qui bouge,
		// on doit notifier ces coordonnees.
		this.positionPanneauXSouris = arg0.getX();
		this.positionPanneauYSouris = arg0.getY();

		
		
		
		
		if (this.getMode() == Representation2D.MODE_DEPLACEMENT) {
			try {
				
				// ca ca marche :::
//				Point p = this.retrouveVeritablePointAPartirDeCoordonneesSurJPanel(arg0.getX(), arg0.getY());
//				this.getPointCentre().setX(this.getPointCentre().getX() + pourLeDeplacementX - p.getX()) ;
//				this.getPointCentre().setY(this.getPointCentre().getY() - pourLeDeplacementY + p.getY()) ;
//				

				
				
				// ca aussi maintenant !! et mieu en zoom profond ..
				while (this.pourLeDeplacementXCoordonnesSurPanneau<arg0.getX())
				{
					this.pourLeDeplacementXCoordonnesSurPanneau+=1 ;
					this.deplaceAGauche() ;
				}
				
				while (this.pourLeDeplacementXCoordonnesSurPanneau>=arg0.getX())
				{
					this.pourLeDeplacementXCoordonnesSurPanneau-=1 ;
					this.deplaceADroite() ;
				}
				
				
				while (this.pourLeDeplacementYCoordonnesSurPanneau<arg0.getY())
				{
					this.pourLeDeplacementYCoordonnesSurPanneau+=1 ;
					this.deplaceEnHaut() ;
				}
				
				while (this.pourLeDeplacementYCoordonnesSurPanneau>=arg0.getY())
				{
					this.pourLeDeplacementYCoordonnesSurPanneau-=1 ;
					this.deplaceEnBas() ;
				}
				
				
				
			} catch (ArithmeticException e) {
				this.setZoom(100);
				this.setPointCentre(new Point(0, 0));
			}
		}
		repaint();

	}

	// quand la souris bouge
	// et qu aucun bouton de la souris n est enfonce .
	public void mouseMoved(MouseEvent arg0) {
		try {

			Point ptheorique = this.retrouveVeritablePointAPartirDeCoordonneesSurJPanel(
					arg0.getX(),
					arg0.getY());

			// on enregistre pour une utilisation future possible
			// dans le repaint() ;
			this.positionPanneauXSouris = arg0.getX();
			this.positionPanneauYSouris = arg0.getY();

			float differencePourEntrerSurInfoPoint = this.tailleCroix;
			boolean dejasUnSurligne = false;
			for (Point p : this.listePoints) {
				if (dejasUnSurligne) {
					p.setAfficheNumero(false);
				} else {

					if (ptheorique.getX() < p.getX()
							+ differencePourEntrerSurInfoPoint
							&& ptheorique.getX() > p.getX()
									- differencePourEntrerSurInfoPoint
							&& ptheorique.getY() < p.getY()
									+ differencePourEntrerSurInfoPoint
							&& ptheorique.getY() > p.getY()
									- differencePourEntrerSurInfoPoint) {
						p.setAfficheNumero(true);
						dejasUnSurligne = true;
					} else {
						p.setAfficheNumero(false);
					}
				}
			}
			if (dejasUnSurligne)
				this.repaint();
		} catch (ArithmeticException e) {
			this.setZoom(100);
			this.setPointCentre(new Point(0, 0));
			this.repaint();
			return;
		}
		if (arg0.getX()<this.zoneinfosSourisX && arg0.getY()<this.zoneinfosSourisY )
			this.montrerinformations  = true ;
		else
			this.montrerinformations = false ;
		this.repaint();
	}

	
	
	
	private String getMode() {
		return mode_actuel;
	}

	
	
	
	public void mouseClicked(MouseEvent arg0) {
		// pour les points pres de la souris :

		// pour le bouton 2 de la souris :
		if (arg0.getButton() == 3) {
			for (Point p : listePoints) {
				// on est pres de p
				if (p.isAfficheNumero()) {
					ChoixPointPopupMenu pm = new ChoixPointPopupMenu(this, p,listeDesEcouteurPourPassageEtatPrecedantSuivant);
					pm.show(this, arg0.getX(), arg0.getY());
					return;
				}
			}
			ChoixHorsPointPopupMenu pm = new ChoixHorsPointPopupMenu(this,listeDesEcouteurPourPassageEtatPrecedantSuivant);
			pm.show(this, arg0.getX(), arg0.getY());
		}
	}

	
	
	
	public void mouseEntered(MouseEvent arg0) {
	}

	
	
	
	public void mouseExited(MouseEvent arg0) {
	}

	
	
	
	public void mousePressed(MouseEvent arg0) {
		
		// les coordonnes pour le dragged.
		// on notifie ici les coordonnees
		// du point de souris
		// on aura plus qu a faire un decalage
		// de la difference avec ce point. ;)
		pourLeDeplacementXCoordonnesSurPanneau = arg0.getX();
		pourLeDeplacementYCoordonnesSurPanneau = arg0.getY();

		
		// on regarde si on a clique sur un point,
		// auquel cas on notifie les listeners.
		// ca donne une interface plus reactive que de faire cet
		// evenement sur un mouse cliqued.
		// sinon on est oblige d attendre
		// que l utilisateur leve le clik
		// et encore que ce soit exactement (au pixel pres)
		// au meme endroit que la ou il a appuye
		//
		// speciale dedicace a mon beau pere.
		// un jour tu saura utiliser une souris
		// et lever au meme endroit que la ou
		// tu a appuye.
		// et la le monde t appartiendra
		//
		// courage...
		if (arg0.getButton()==MouseEvent.BUTTON1)
		for (Point p : listePoints) {
			if (p.isAfficheNumero())
				for (SelectionMatriceListener listener : listeDesEcouteurPourSelectionDeMatrice) {
					listener.selectionMatrice(p.getNumeroMatriceCorrespondante()) ;
				}
		}
		
		
		
		// si on zoome trop
		// il y aura une division par zero.
		// qui fait planter le programme sans lever d exception speciale
		// du moins le main le releve pas cette exception.
		// donc on ne comprend rien ;)
		// donc ici on fais une capture d exception
		// 
		try {
			
			// ancienne maniere de gerer le mouse dragged
//			Point p = this.retrouveVeritablePointAPartirDeCoordonneesSurJPanel(
//					arg0.getX(), arg0.getY());
//			pourLeDeplacementX = (int)p.getX();
//			pourLeDeplacementY = (int)p.getY();

			
			
			
			this.mode_actuel = Representation2D.MODE_DEPLACEMENT;
		} catch (ArithmeticException e) {
			// si il y a eut une division par zero
			// on remet les valeurs par defaut.
			this.setZoom(100);
			this.setPointCentre(new Point(0, 0));
			this.repaint();
			return;
		}
		// }
	}

	
	// lorsqu on releve le clik de souris
	public void mouseReleased(MouseEvent arg0) {
		// on ne fait rien a part changer de mode.
		this.mode_actuel = Representation2D.MODE_DEFAUT;
	}

	
	/**
	 * la molette de souris
	 * 
	 * ==> le maniement du zoom
	 * (change le zoom et les intervalles du grillage).
	 * 
	 */
	public void mouseWheelMoved(MouseWheelEvent arg0) {

		this.mode_actuel = Representation2D.MODE_ZOOM;

		// -1 c'est en avant et 1 c'est en arriere ..
		// mais perso je pense que si on avait une souris
		// qui peut faire deux mouvement en meme temp,
		// les valeurs serons -2 ou 2.
		// n ayant pas ce genre de souris (imaginaire ?)
		// je n ai pas pu tester ce cas
		// faut le savoir
		//
		if (arg0.getWheelRotation() == -1) {
			// ce try va capturer la division par zero
			// (cette exception n est pas levee sur les floats)
			// en effet le float vaut a ce moment : Float.NaN
			// qui est a peut pres equivalent a + l infinit,, voire - l infinit, voire les deux ...
			try {
				Point vraiPoint = this.retrouveVeritablePointAPartirDeCoordonneesSurJPanel(
								arg0.getX(), arg0.getY());

				// la valeur de decalage pour qu on ai
				//  l impression de zoomer a l endroit
				// du pointeur de souris.
				// c est en tatonnant que j ai trouve
				// pas trouve de megatrucs sur le net.
				// ca arrive souvent not ?
				
				int rattrapageX = (((int)vraiPoint.getX() * this.getZoom() / 100 - (int)vraiPoint.getX()
						* (this.getZoom() - this.getVitesseZoom()) / 100));
				int rattrapageY = -(((int)vraiPoint.getY() * this.getZoom() / 100 - (int)vraiPoint.getY()
						* (this.getZoom() - this.getVitesseZoom()) / 100));

				
				// du coup maintenant on centre en premant en compte le decalage
				this.getPointCentre().setX(
						this.getPointCentre().getX() + rattrapageX);
				this.getPointCentre().setY(
						this.getPointCentre().getY() + rattrapageY);

				
				// on change le zoom pour de vrai
				this.setZoom((int)(this.getZoom() * 1.5) );//this.getVitesseZoom()/100);
				this.repaint();
			} catch (ArithmeticException e) {
				this.setZoom(100);
				this.setPointCentre(new Point(0, 0));
				this.repaint();
				return;
			}
		}
		// en arriere
		if (arg0.getWheelRotation() == 1) {
			try {
				Point vraiPoint = this.retrouveVeritablePointAPartirDeCoordonneesSurJPanel(
								arg0.getX(), arg0.getY());

				// le rattrapage . NoooooooNNNN
				// et si .
				int rattrapageX = -(((int)vraiPoint.getX() * this.getZoom() / 100 - (int)vraiPoint.getX()
						* (this.getZoom() - this.getVitesseZoom()) / 100));
				int rattrapageY = (((int)vraiPoint.getY() * this.getZoom() / 100 - (int)vraiPoint.getY()
						* (this.getZoom() - this.getVitesseZoom()) / 100));

				this.getPointCentre().setX(
						this.getPointCentre().getX() + rattrapageX);
				this.getPointCentre().setY(
						this.getPointCentre().getY() + rattrapageY);

				this.setZoom((int) (this.getZoom() / 1.5)) ;//this.getVitesseZoom()/100);
				this.repaint();

			} catch (ArithmeticException e) {
				this.setZoom(100);
				this.setPointCentre(new Point(0, 0));
				this.repaint();
				return;
			}
		}

	}

	
	
	
	
	
	/**
	 * retrouve le point a partir des coordonnes sur le panneau.
	 * 
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	private Point retrouveVeritablePointAPartirDeCoordonneesSurJPanel(float x, float y) {

		// on s adapte a pointCentre
		x = x + pointCentre.getX();
		y = y + pointCentre.getY();


		// on se place comme si le centre etait a 0,0
		float decalageX = this.getWidth() / 2;
		float decalageY = this.getHeight() / 2;

		x = x - decalageX;
		y = y - decalageY;


		// enfin le zoom
		x = x * 100 / this.getZoom();
		y = y * 100 / this.getZoom();
		// x = -x ;
		y = -y;

		return new Point(x, y);
	}

	
	
	
	
	
	/**
	 * trouve le point sur le JPanel a partir des coordonnees reelles du point.
	 * 
	 * @param p
	 * @return
	 */
	private Point retrouveCoordonneesAPartirDuVraiPoint(Point p) {

		// on se place comme si le centre etait a 0,0
		float decalageX = this.getWidth() / 2;
		float decalageY = this.getHeight() / 2;

		// puis on s adapte a pointCentre:
		decalageX = decalageX - pointCentre.getX();
		decalageY = decalageY - pointCentre.getY();

		float valeurPointXAvecZoom = p.getX() * this.getZoom() / 100;
		float valeurPointYAvecZoom = p.getY() * this.getZoom() / 100;

		float avecDecalageX = valeurPointXAvecZoom + decalageX;
		float avecDecalageY = valeurPointYAvecZoom - decalageY;
		avecDecalageY = -avecDecalageY;


		return new Point(avecDecalageX, avecDecalageY);

	}

	public int getVitesseZoom() {
		return vitesseZoom;
	}

	public void setVitesseZoom(int vitesseZoom) {
		this.vitesseZoom = vitesseZoom;
	}

	public void afficherMasquerLaFonctionAOpimiser() {
		this.afficherLaFonctionAOptimiser = !this.afficherLaFonctionAOptimiser;
		repaint();
	}


	public void afficherMasquerLeCheminVersResultat() {
		this.afficherResultat = !this.afficherResultat;
	}

	public boolean isAfficherCadrillage() {
		return afficherCadrillage;
	}

	public void setAfficherCadrillage(boolean afficherCadrillage) {
		this.afficherCadrillage = afficherCadrillage;
	}

	public boolean isAfficherPointRouge() {
		return afficherPointRouge;
	}

	public void setAfficherPointRouge(boolean b) {
		this.afficherPointRouge = b;
	}

	public void keyPressed(KeyEvent arg0) {
		System.out.println("appuy� sur" + arg0.getKeyCode());
		// petit g => grille
		if (arg0.getKeyChar() == 'g')
			setAfficherCadrillage(!isAfficherCadrillage());
		repaint();
	}

	public void keyReleased(KeyEvent arg0) {
		System.out.println("appuy� 3 sur" + arg0.getKeyCode());

	}

	public void keyTyped(KeyEvent arg0) {
		System.out.println("appuy� 2 sur" + arg0.getKeyCode());

	}

	
	/**
	 * 
	 * enleve une equation du panneau
	 * 
	 * 
	 * @param x1
	 * @param x2
	 * @param signe
	 * @param partieDroite
	 */
	public void retirerEquation2D(float x1, float x2, String signe, float partieDroite) {
		// ca en supprimera un maximum.
		// 0 sinon.
		boolean pasEncoreSupprime = true ;
		for (int i = 0; i < listeEquations.size() && pasEncoreSupprime ; i++) {
			if( 
					listeEquations.get(i).getX1()==x1 &&
					listeEquations.get(i).getX2()==x2 &&
					listeEquations.get(i).getOperateur()==signe &&
					listeEquations.get(i).getPartieDroite()==partieDroite
					)
			{
				listeEquations.remove(i) ;
				pasEncoreSupprime = false ;
			}
		}
		repaint() ;
	}
	
	public void supprimerEquation2D(Equation2D eq)
	{
		listeEquations.removeElement(eq);	
		repaint();
	}
	
	public String getLibelleX1() {
		return this.libelleX1;
	}

	public String getLibelleX2() {
		return this.libelleX2;
	}

	public void setLibelleX1(String libelle) {
		this.libelleX1 = libelle ;
		repaint();
	}

	public void setLibelleX2(String libelle) {
		this.libelleX2 = libelle ;
		repaint();
	}

	
	/**
	 * enleve un point du panneau.
	 * 
	 * @param x1
	 * @param x2
	 */
	public void retirerPoint(float x1, float x2) {
		// ca en supprimera un maximum.
		// 0 sinon.
		boolean pasEncoreSupprime = true ;
		for (int i = 0; i < listePoints.size() && pasEncoreSupprime ; i++) {
			if( 
					listePoints.get(i).getX()==x1 &&
					listePoints.get(i).getY()==x2
					)
			{
				listePoints.remove(i) ;
				pasEncoreSupprime = false ;
			}	
		}
		repaint() ;
	}

	/**
	 * enleve un point du panneau.
	 * 
	 * @param x1
	 * @param x2
	 */
	public void retirerToutLesPoints() {
		for (int i = 0; i < listePoints.size() ; i++) {

				listePoints.remove(i) ;
		}
		repaint() ;
	}

	
	/**
	 * 
	 * la on met des listeners sur<br>
	 * le click sur un point.<br>
	 * l ecouteur sera avertis si l tilisateur<br>
	 * clique sur le point.<br>
	 * 
	 * @param listener
	 */
	public void ajouterSelectionMatriceListener(SelectionMatriceListener listener) {
		this.listeDesEcouteurPourSelectionDeMatrice .add(listener) ;
	}

	
	
	
	
	public Cursor getCurseurDefaut() {
		return curseurDefaut;
	}

	public void setCurseurDefaut(Cursor curseurDefaut) {
		this.curseurDefaut = curseurDefaut;
	}

	public Cursor getCurseurPassageSurPoint() {
		return curseurPassageSurPoint;
	}

	public void setCurseurPassageSurPoint(Cursor curseurPassageSurPoint) {
		this.curseurPassageSurPoint = curseurPassageSurPoint;
	}

	
	/**
	 * changer la couleur d un point:
	 * 
	 * @param x1
	 * @param x2
	 * @param c
	 */
	public void changerCouleurPoint(int x1, int x2, Color c) {
		// on changera la couleur pour un point maximum.
		// 0 sinon.
		boolean pasEncoreChangeCouleur = true ;
		for (int i = 0; i < listePoints.size() && pasEncoreChangeCouleur ; i++) {
			if( 
					listePoints.get(i).getX()==x1 &&
					listePoints.get(i).getY()==x2
					) 
			{
				listePoints.get(i).setCouleur(c) ;
				pasEncoreChangeCouleur = false ;
			}
		}
		repaint() ;
	}

	
	
	
	/**
	 * change la couleur de la ligne
	 * correspondant a l equation 2D
	 * dont les proprietes correspondent
	 * aux parametres.
	 * 
	 * @param x1
	 * @param x2
	 * @param signe
	 * @param partieDroite
	 * @param c
	 */
	public void changerCouleurEquation2D(float x1, float x2, String signe, float partieDroite, Color c) {
		// changera pour un maximum.
		// 0 sinon.
		boolean pasEncoreChangeCouleur = true ;
		for (int i = 0; i < listeEquations.size() && pasEncoreChangeCouleur ; i++) {
			if( 
					listeEquations.get(i).getX1()==x1 &&
					listeEquations.get(i).getX2()==x2 &&
					listeEquations.get(i).getOperateur()==signe &&
					listeEquations.get(i).getPartieDroite()==partieDroite
					)
			{
				listeEquations.get(i).setCouleur(c) ;
				pasEncoreChangeCouleur = false ;
			}
		}
		repaint() ;

	}
	
	
	
	public void deplaceADroite() {
		this.getPointCentre().setX(this.getPointCentre().getX()+1) ;
	}

	public void deplaceAGauche() {
		this.getPointCentre().setX(this.getPointCentre().getX()-1) ;
	}

	public void deplaceEnHaut() {
		this.getPointCentre().setY(this.getPointCentre().getY()-1) ;
	}

	public void deplaceEnBas() {
		this.getPointCentre().setY(this.getPointCentre().getY()+1) ;
	}

	public void addEtatPrecedantSuivantListener(EtatPrecedantSuivantListener listener) {
		this.listeDesEcouteurPourPassageEtatPrecedantSuivant .add(listener) ;
	}

	public void selectionnerEtatPrecedant() {
		System.out.println("demande d etat precedant");
		
	}

	public void selectionnerEtatSuivant() {
		System.out.println("demande d etat suivant");
		
	}

}
